import { streamCollector } from "@smithy/node-http-handler";
import { SdkStream, SdkStreamMixin } from "@smithy/types";
import { fromArrayBuffer } from "@smithy/util-buffer-from";
import { buffer, stream, util } from "@kit.ArkTS";

// import { sdkStreamMixin as sdkStreamMixinReadableStream } from "./sdk-stream-mixin.browser";

const ERR_MSG_STREAM_HAS_BEEN_TRANSFORMED = "The stream has already been transformed.";

/**
 * The function that mixes in the utility functions to help consuming runtime-specific payload stream.
 *
 * @internal
 */
export const sdkStreamMixin = (streamMixin: stream.Readable): SdkStream<stream.Readable> => {

  let transformed = false;
  const transformToByteArray = async () => {
    if (transformed) {
      throw new Error(ERR_MSG_STREAM_HAS_BEEN_TRANSFORMED);
    }
    transformed = true;
    return await streamCollector(streamMixin);
  };

  return Object.assign<stream.Readable, SdkStreamMixin>(streamMixin, {
    transformToByteArray,
    transformToString: async (encoding?: string) => {
      const buf = await transformToByteArray();
      if (encoding === undefined || buffer.isEncoding(encoding)) {
        return fromArrayBuffer(buf.buffer, buf.byteOffset, buf.byteLength).toString(encoding);
      } else {
        return util.TextDecoder.create(encoding).decodeToString(buf)
      }
    }
    // transformToWebStream: () => {
    //   if (transformed) {
    //     throw new Error(ERR_MSG_STREAM_HAS_BEEN_TRANSFORMED);
    //   }
    //   if (stream.readableFlowing !== null) {
    //     // Prevent side effect of consuming webstream.
    //     throw new Error("The stream has been consumed by other callbacks.");
    //   }
    //   if (typeof Readable.toWeb !== "function") {
    //     throw new Error("Readable.toWeb() is not supported. Please ensure a polyfill is available.");
    //   }
    //   transformed = true;
    //   return Readable.toWeb(stream) as ReadableStream;
    // },
  });
};
